<?php
namespace app\gym\model;
use app\common\model\Base;
use app\publictool\controller\PublicTool;
use app\publictool\controller\MsgTpl;
use think\Validate;
//会员与教练签约的模块
use app\user\model\MemberSigningApplication;
use app\common\model\Observice;
use think\Loader;
/**
*会员签约教练的模型
*/
/**
*CREATE TABLE `gym_signing_fitness_instructor` (
* `gym_id` char(64) NOT NULL COMMENT '健身房的编号',
* `member_id` char(64) NOT NULL COMMENT '会员的编号',
* `fitness_instructor_id` char(64) NOT NULL COMMENT '当前教练的编号',
* `bought_class` int(4) NOT NULL COMMENT '当前会员已经购买的课时',
* `rest_of_class` int(4) NOT NULL COMMENT '当前会员剩余的课时',
* `create_time` int(15) unsigned NOT NULL COMMENT '创建的时间可以理解为签约的时间',
* `last_update_time` int(15) unsigned NOT NULL COMMENT '最后修改的时间(也可以作为会员与教练解约的时间)',
* `status` int(1) unsigned NOT NULL DEFAULT '1' COMMENT '签约的状态1:已经签约,0:已经解约',
* KEY `gym_signing_fitness_instructor_gym_id_IDX` (`gym_id`,`member_id`,`fitness_instructor_id`,`status`) USING BTREE
*)ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='会员与教练签约的模块'
*/
class MemberSigning extends Base{
    protected $table = 'gym_signing_fitness_instructor';
    protected static $cacheTag = 'signing_fitness_instructor';
    protected static  $autoPushCreateTime = true; //自动添加时间
    protected static  $autoPushUpdateTime = true; //自动添加修改时间
    protected static $inputData = []; //输入的信息

    /**
    *会员对教练进行签约,和当前会员签约的模型
    *其中会接收到两个分支逻辑
    *1. 教练同意签约
    *2. 教练拒绝签约
    */
    public static function signing(){
        //教练与会员的签约
        return self::couSave(
          [
            //会员的id
            ['member_id','require','会员的编号不能为空！'],
            ['fitness_instructor_id','require','教练的编号不能为空！'],
            ['gym_id','require','健身房的编号不能为空！'],
            ['bought_class','require','会员的总课时不能为空！'],
            ['rest_of_class','require','会员的剩余课时不能为空！']
          ],
          function($input,$self){
              $dataObject = new $self();
              $allowField =true;
              if($dataObject->where(['fitness_instructor_id'=>$input['fitness_instructor_id'],'member_id'=>$input['member_id'],'gym_id'=>$input['gym_id']])->count() > 0){
                  $input['status'] = 1;
                  return $dataObject->allowField($allowField)->save($input,['fitness_instructor_id'=>$input['fitness_instructor_id'],'member_id'=>$input['member_id'],'gym_id'=>$input['gym_id']]);
              }
              //与会员进行签约
              return $dataObject->data($input)->allowField($allowField)->isUpdate(false)->save();
          }
        );
    }


    /**
     * [historyClassCount 教练的历史总课时]
     * @return [type] [description]
     */
    public static function historyClassCount($info){
          $where = ['fitness_instructor_id'=>$info['fitness_id']];
          $result = self::where($where)->sum('bought_class');
          return $result;
    }

    // $signing = new self();
    // $input = self::getInputData();
    // $validateColumn = config('signing.member_signing_validate');
    // $rules = $validateColumn['rules'];
    // $message = $validateColumn['message'];
    // $validate = new Validate($rules,$message);
    // if(!$validate->check($input)){
    //     abort(-0006,$validate->getError());
    // }
    // Observice::addObserivce('\\app\\user\\model\\AlertsMsg',['type'=>'member_siging','title'=>'签约','data'=>self::getInputData()]);
    // Observice::notify();
    // exit;
    // if(self::alreadySigning()){abort(-0007,'不能重复签约！');}
    // $input['create_time'] = time(); //签约时间
    // $input['last_update_time'] = time(); //是最后修改时间，也可以作为解约时间
    // //下面这些可以拿走
    // $save = $signing->data($input)->isUpdate(false)->save();
    // if(!$save){
    //    abort(-0002,'签约失败,请重试！');
    // }
    // //确认签约操作通知接受者
    // return true;

    /**
    *已经签约
    *判断是否已经签约，如果已经签约的话返回true
    *否则返回false
    *@param $status 是否签约的状态值
    *@return boolean true|false
    */
    public static function alreadySigning($status=1,$memberId='',$fitness='',$gym_id=''){
        return self::memberRelation($status,$memberId,$fitness,$gym_id) > 0 ? true : false;
    }


    /**
    *已经解约
    */
    public static function alreadyUnSigning($status=0,$memberId='',$fitness='',$gym_id=''){
        return self::memberRelation($status,$memberId,$fitness,$gym_id) > 0? true : false;
    }


    /**
     * [signingMemberCount 教练下面签约会员的数量统计,仅仅只是进行数量的统计]
     * @return [type] [description]
     */
    public static function signingMemberCount($fitnessId){

        $where = ['fitness_instructor_id'=>$fitnessId,'status'=>1];
        $result = self::where($where);
        $response = $result->count();
        return $response;
    }


    /**
     * [fitnessRestClassInfoSum 获取教练剩余课时的总数]
     * 这个函数是没有缓存的
     * @param  [String] $fitness [教练的编号]
     * @return [Int]          [Int 返回教练所有的剩余课时]
     */
    public static function fitnessRestClassInfoSum($fitness){
        $where = ['fitness_instructor_id'=>$fitness,'status'=>1];
        $result = self::where($where);
        $response = $result->sum('rest_of_class');
        $response = is_null($response)?0:$response;
        return $response;
    }
    /**
    *查询会员与教练的关系
    *@param $status 查询状态值
    *@param $memberId 会员id
    *@param $fitness 健身教练的id
    *@param $gymId  健身房的id
    */
    public static function memberRelation($status=1,$memberId='',$fitness='',$gymId=''){
         $input = self::$inputData;
         $where = [];
         if(!empty($input) && empty($memberId)){
              $memberId = self::getInputData('member_id');
              $fitness = self::getInputData('fitness_instructor_id');
              $gymId = self::getInputData('gym_id');
         }
         if(empty($memberId)){
             abort(-0007,'会员id不能为空！');
         }

         if(empty($fitness)){
             abort(-0010,'教练id不能为空');
         }

         if(empty($gymId)){
             abort(-0011,'健身房id不能为空！');
         }

         $where = ['member_id'=>$memberId,'fitness_instructor_id'=>$fitness,'gym_id'=>$gymId,'status'=>$status];
         return self::where($where)->count();
    }


    /**
    *设置会员的必填参数
    */
    public static function setParams(array $params=[]){
        //拼接后设置内容
        self::$inputData = PublicTool::replaceInputData([
             'fitness_instructor_id'=>'fitness_id',
             'rest_of_class'=>'rest_class'
            ],$params);
    }

    /**
    *查询当前会员所属的教练和健身房
    */
    public static function info(array $input=[],$field=[],$limit=1,$page=1,$order='gs.create_time desc'){
        if(!array_key_exists('member_id',$input)){
            abort(-0003,'没有必要的用户id');
        }
        $field=[
          'gs.gym_id', //健身房的编号
          'gs.fitness_instructor_id as fitness_id', //教练的编号
          'gs.bought_class',//全部累计的课时
          'gs.rest_of_class',//剩余的课时
          'gi.store_title',//健身房的名称
          'gi.profile',//健身房的简介
          'gi.pictures',//健身房的图片
          'ui.nick_name',//健身教练的昵称
          'ui.head_figure'//健身教练的头像
        ];
        $memberId = $input['member_id'];
        //$count = self::signingSum($memberId) < 1 ? 0 : self::signingSum($memberId);
        $where = ['gs.member_id'=>$memberId,'gs.status'=>1];
        $object = self::where($where)->alias('gs')->field($field);
        $object->join('__GYM_INFO__ gi','gs.gym_id = gi.unique_id','LEFT');
        $object->join('__USER_INFO__ ui','gs.fitness_instructor_id = ui.uuid','LEFT');
        $result = $object->order($order)->limit($limit)->field($field);
        $response = self::infoOfCache($result);
        return $response;
    }

    /**
     * [memberTransfer 会员转移的操作]
     * @return [type] [description]
     */
    public static function memberTransfer(){
        self::couSave(
          [
            ['fitness_id','require','当前的教练编号不能为空！'],
            ['members','require','要转移的会员不能为空！'],
            ['to_fitness_id','require','转移给哪一个教练！']
          ],
          function($input,$self){
              if($input['fitness_id'] == $input['to_fitness_id']){
                    abort(-00023,"转移的教练与操作的教练相同");
              }
              $dataObj = new $self();
              $sigining  = [];
              $where = ['fitness_instructor_id'=>$input['fitness_id'],'member_id'=>['in',$input['members']]];
              $members = collection(self::where($where)->select())->toArray();
              foreach($members as $key => $val){
                    $sigining[] =[
                      'fitness_instructor_id'=>$input['to_fitness_id'],
                      'status'=>1,
                      'last_update_time'=>time(),
                      'create_time'=>time(),
                      'rest_of_class'=>$val['rest_of_class'],
                      'bought_class'=>$val['bought_class'],
                      'gym_id'=>$val['gym_id'],
                      'member_id'=>$val['member_id'],
                    ];
              }
              if($dataObj->save(['status'=>0],$where)){

                  return $dataObj->saveAll($sigining);

              }
          }
        );
        return [];
    }

    /**
     * [fitnessMembers 查看教练签约的会员]
     * @return [array] [返回数组信息]
     */
    public static function fitnessMembers($fitnessId=null){
        //找到目前和教练签约的会员
        if(empty($fitnessId)){
            abort(-0031,'教练的编号不能为空！');
        }
        //查询与健身房签约的用户
        $sql = self::where('fitness_instructor_id','in',$fitnessId)->where(['status'=>1]);
        $response = self::infoOfCache($sql);
        return $response;
    }

    /**
     * [fitnessGymMebers 获取教练在指定健身房下签约的会员]
     * @param  array  $info [教练的编号和健身房的编号]
     * @return [array]       [返回签约的会员信息]
     */
    public static function fitnessGymMebers($info=[]){
        $where = [
        'fitness_instructor_id'=>$info['fitness_instructor_id'],
        'status'=>1,
        'gym_id'=>$info['gym_id']
      ];
      $result = self::where($where);
      $response = self::infoOfCache($result,true);
      return $response;
    }

    //获取会员剩余课时
    public static function restClassInfo(array $input=[]){
         if(empty($input)){
            $input = self::getInputData();
            $memberId = $input['member_id'];
            $gymId = $input['gym_id'];
            $fitnessId = $input['fitness_instructor_id'];
         }else{
           $memberId = $input['member_id'];
           $gymId = $input['gym_id'];
           $fitnessId = $input['fitness_id'];
         }
         if(!array_key_exists('member_id',$input)){
                abort(-0016,'会员编号不存在！');
         }

         if(!array_key_exists('gym_id',$input)){
                abort(-0015,'健身房编号不存在！');
         }

         if(!array_key_exists('fitness_id',$input)){
                abort(-0014,'教练编号不存在！');
         }
         //赋值操作
         //此处是检测此会员是否与健身房有过签约，如果没有签约过就会显示0
         if(self::signingSum($memberId) == 0){
            return 0; //就是便是当前会员剩余的0课时
         }
         //此处检测结束
         $where = ['member_id'=>$memberId,'gym_id'=>$gymId,'fitness_instructor_id'=>$fitnessId];
         return self::where($where)->field(['rest_of_class','bought_class'])->find()->toArray();

    }


    /**
     * [fitnessCountInfo 教练下面的统计信息]
     * @return [type] [description]
     */
    public static function fitnessCountInfo( $info = [] ){
        if(array_key_exists('fitness_instructor_id',$info)){
            $where = ['ms.fitness_instructor_id'=>$info['fitness_instructor_id']];

        }
        if(array_key_exists('gym_id',$info)){
          $where = ['ms.gym_id'=>$info['gym_id']];
        }

        $sqlQuery = self::sqlParams($info,
        [
          'field'=>[
            'ms.gym_id',
            'ms.member_id',
            'ms.fitness_instructor_id',
            'count(ms.member_id) as member_count',
            'sum(ms.rest_of_class) as rest_of_class_count',
            'ms.bought_class',
            'usi.uuid',
            'usi.nick_name',
            'usi.head_figure'
          ],
          'limit'=>10,
          'page'=>1,
          'order'=>'count(member_id) desc',
        ]);
        $where['ms.status'] = 1;
        $sqlResult = function($where,$sqlQuery){
            return self::where($where)->alias('ms')->join('__USER_INFO__ usi','ms.fitness_instructor_id = usi.uuid','INNER')->group('ms.fitness_instructor_id');
        };
        $count = $sqlResult($where,$sqlQuery)->count();
        $result = $count > 0 ? self::infoOfCache($sqlResult($where,$sqlQuery)->field($sqlQuery['field'])->limit($sqlQuery['limit'])->page($sqlQuery['page'])->order($sqlQuery['order'])) :[];
        return MsgTpl::createListTpl($result,$count,$sqlQuery['limit'],$sqlQuery['page']);
    }

    /**
     * [remainingClassHour 会员剩余课时列表]
     * @return [type] [description]
     */
    public static function remainingClassHour($info){
        if(array_key_exists('gym_id',$info)){
            $where = ['ms.gym_id'=>$info['gym_id'],'ms.status'=>1];
        }

        if(array_key_exists('fitness_instructor_id',$info)){
            $where = ['ms.fitness_instructor_id'=>$info['fitness_instructor_id'],'ms.status'=>1];
        }
        $sqlQuery = self::sqlParams($info,[
          'field'=>[
              'ms.gym_id',
              'ms.fitness_instructor_id',
              'ms.rest_of_class',
              'ms.member_id',
              'usi.head_figure',
              'usi.nick_name',
              'usi.name'
          ],
          'limit'=>10,
          'page'=>1,
          'order'=>'ms.rest_of_class asc',
        ]);
        $sqlResult = function($where,$sqlQuery){

              return self::where($where)->alias('ms')->join('__USER_INFO__ usi','ms.member_id = usi.uuid','INNER');

        };
        $count = $sqlResult($where,$sqlQuery)->count();
        $result = $count > 0 ? self::infoOfCache($sqlResult($where,$sqlQuery)->field($sqlQuery['field'])->limit($sqlQuery['limit'])->page($sqlQuery['page'])->order($sqlQuery['order'])) :[];
        return MsgTpl::createListTpl($result,$count,$sqlQuery['limit'],$sqlQuery['page']);
    }



    /**
     * [remainingClassHour 会员剩余课时列表]
     * @return [type] [description]
     */
    public static function remainingClassHourContent($info){
        $where = ['ms.member_id'=>$info['member_id'],'ms.gym_id'=>$info['gym_id'],'ms.status'=>1];
        $sqlQuery = self::sqlParams($info,[
          'field'=>[
              'ms.gym_id',
              'ms.fitness_instructor_id',
              'ms.rest_of_class',
              'ms.member_id',
              'ms.bought_class',
              'usi.head_figure',
              'usi.nick_name',
              'usi.name'
          ],
        ]);
        $sqlResult = function($where,$sqlQuery){
              return self::where($where)->alias('ms')->join('__USER_INFO__ usi','ms.member_id = usi.uuid','INNER');

        };
        $count = $sqlResult($where,$sqlQuery)->count();
        $result = $count > 0 ? self::infoOfCache($sqlResult($where,$sqlQuery)->field($sqlQuery['field'])) :[];
        return $result;
    }

  /**
  *发起签约
  *签约是由会员发起的
  */
  public static function initiate(array $input=[]){
        if(empty($input)){
            $input = self::getInputData();
            $input['fitness_id'] = $input['fitness_instructor_id'];
            unset($input['fitness_instructor_id']);
        }
        if(!array_key_exists('fitness_id',$input)){
            abort(-0017,'教练的唯一标识必须！');
        }
        if(!array_key_exists('member_id',$input)){
            abort(-0020,'会员的唯一标识必须存在！');
        }
        //会员发起签约教练同意后进行签约
        Observice::addObserivce('\\app\\user\\model\\AlertsMsg',['type'=>'member_siging','title'=>'签约','data'=>$input,'content'=>'请求签约']);
        Observice::notify();
  }

  /**
   * [gymMemberCount 健身房签约会员的数量]
   * @return [array] [返回数据的内容]
   */
  public static function gymMemberCount($info=[]){
      if(array_key_exists('gym_id', $info)){
          $where = is_array($info['gym_id'])? ['gym_id'=>['in',$info['gym_id']]]:['gym_id'=>$info['gym_id']];
      }else{
        abort('参数错误！');
      }
      $result = self::where($where);
      if(array_key_exists('date',$info)){
          $result->whereTime('create_time',$info['date']);
      }
      $result->where(['status'=>1]);
      return $result->count();
  }




  /**
   * [gymMemberSum 统计会员的内容]
   * @param  array  $info [description]
   * @return [type]       [description]
   */
  public static function gymMemberSum($info=[]){
    if(array_key_exists('gym_id', $info)){
        $where = is_array($info['gym_id'])? ['gym_id'=>['in',$info['gym_id']],'status'=>1]:['gym_id'=>$info['gym_id'],'status'=>1];
    }else{
      abort('参数错误！');
    }
      $result = self::where($where);
      return $result->sum($info['field']);
  }






  /**
  *教练拒绝发起签约
  */
  public static function rejectSigning($input=[]){
        if(empty($input)){
            $input = self::getInputData();
        }
        if(array_key_exists('fitness_id',$input)){
            abort(-0017,'教练的唯一标识必须！');
        }
        if(array_key_exists('member_id',$input)){
            abort(-0020,'会员的唯一标识必须存在！');
        }
        Observice::addObserivce('\\app\\user\\model\\AlertsMsg',['type'=>'reject_member_siging','title'=>'教练拒绝','data'=>$input,'content'=>'教练拒绝了您的签约！']);
        Observice::notify();
  }


    /**
    *会员和教练进行解约的操作
    */
   public static function unsigning(){
        $input = self::getInputData();
        PublicTool::checkInputData($input);
        $fitnessStock = self::where(['gym_id'=>$input['gym_id'],'member_id'=>$input['member_id'],'status'=>1])->find();
        self::setInputData('fitness_instructor_id',$fitnessStock['fitness_instructor_id']);
        $input['fitness_instructor_id']= $fitnessStock['fitness_instructor_id'];
        $validateColumn = config('signing.member_unsigning_validate');
        $rules = $validateColumn['rules'];
        $message = $validateColumn['message'];
        $validate = new Validate($rules,$message);
        //检查inputData的错误
        if($validate->check($input)){abort('-0001',$validate->getError());}
        //确认之间的关系
        if(self::alreadyUnSigning()){abort(-0006,'您和教练之间没有签约或者已经解约！');}
        $where['gym_id'] =self::getInputData('gym_id');
        $where['member_id'] = self::getInputData('member_id');
        $where['status'] = 1;
        $unSigning = new self();
        $save = $unSigning->save(['last_update_time'=>time(),'status'=>0],$where);
        if(!$save){
            abort(-0007,'解约失败，请重试！');
          }
          \app\gym\model\Unsigning::setInputData(
            [
              'member_id'=>$input['member_id'],
              'fitness_id'=>$input['fitness_instructor_id'],
              'gym_id'=>$input['gym_id'],
              'create_time'=>time(),
              'oper_id'=>$input['uuid']
            ]
          );
          \app\gym\model\Unsigning::push();
        return [];
   }

   /**
   *
   *@param $member 用户的唯一标识符,获取当前会员签约健身房或者教练的总数量
   */
   public static function signingSum($memberId=null){
        if(is_null($memberId)){
           $memberId = self::getInputData('member_id');
        }
        $where = ['member_id'=>$memberId,'status'=>1];
        return self::where($where)->count();
   }


   /**
    * [Statistics 会员签约统计]
    */
   public static function Statistics($methods,$info=[]){
      //会员剩余课时的排行榜
      switch(''){

      }
   }

   /**
    * [MemberSpareTime 教练剩余的课时排行榜]
    * @param [array] $info [array]
    */
   protected static function MemberSpareTime($info=[]){
       //找出健身房下面会员的数量
       $where = ['gym_id',$info['gym_id'],'status'=>1];
       $field = ['gym_id',''];
       self::where($where)->select();
       self::infoOfCache();
   }

   /**
    * [MemberFitnessList 会员健身的排行榜]
    */
   protected static function MemberFitnessList($info=[]){

   }

   /**
    * [memberList 教练的会员列表]
    * @return [type] [description]
    */
   public static function memberList($condition){
     $sqlQuery = self::sqlParams($condition,['limit'=>10,'page'=>1,'order'=>'msi.create_time desc','field'=>['msi.id','msi.member_id','msi.gym_id','msi.create_time','usi.name','usi.nick_name','usi.gender','usi.head_figure','usi.phone_num','msi.rest_of_class','msi.bought_class']]);
      $query = function($condition,$sqlQuery){
        $where = ['msi.fitness_instructor_id'=>$condition['uuid'],'msi.status'=>1];
        $result = self::where($where)->alias('msi')->join('__USER_INFO__ usi','msi.member_id = usi.uuid','INNER')->field($sqlQuery['field']);
        return $result->limit($sqlQuery['limit'])->page($sqlQuery['page'])->order($sqlQuery['order']);
      };
      $count = $query($condition,$sqlQuery)->count();
      $response = self::infoOfCache($query($condition,$sqlQuery));
      return  MsgTpl::createListTpl($response,$count,$sqlQuery['limit'],$sqlQuery['page']);

   }

   /**
    * [gymMember 健身房下的会员列表]
    * @return [type] [description]
    */
   public static function gymMemberList($info=[]){
      if(!array_key_exists('gym_id', $info)){
          abort('参数错误！');
      }
      $params = self::sqlParams($info,['limit'=>10,'page'=>1,'order'=>'msi.create_time desc','field'=>
    [
      'msi.*',
      'usi.uuid',
      'usi.nick_name',
      'usi.name'
      ]]);
      $where = ['msi.gym_id'=>$info['gym_id'],'msi.status'=>1];
      $result = function($where,$params){
        $result = self::where($where);
        $result->alias('msi')->join('__USER_INFO__ usi','msi.member_id = usi.uuid','INNER');
        return $result;
      };
      $count = $result($where,$params)->count();
      $response = self::infoOfCache($result($where,$params)->field($params['field'])->limit($params['limit'])->page('page')->order($params['order']));
      return MsgTpl::createListTpl($response,$count,$params['limit'],$params['page']);
   }




   /**
   *会员的剩余课时操作,增加或者减少
   */
   public static function memberHoursOption(){
     self::couSave(
       [
        ['fitness_id','require','教练的编号不能为空！'],
        ['member_id','require','会员的编号不能是空的！'],
        ['gym_id','require','健身房的编号不能是空的 ！'],
        ['hours','require|number',':课程数量必须存在|课程数量必须是整数'],
        ['option','require','课时操作不能是空的！']
       ],
       function($input,$self){
          $dataObject = new $self();
          $where = ['fitness_instructor_id'=>$input['fitness_id'],'member_id'=>$input['member_id'],'gym_id'=>$input['gym_id']];
          $restGroup =  self::where($where)->field(['bought_class','rest_of_class'])->find();
          is_null($restGroup)?abort(-30,'当前教练当前会员并没有签约！'):'';
          $restGroup = $restGroup->toArray();
          switch($input['option']){
            //bought_class 总课时
            //rest_of_class 剩余课时
              case 1:
                //课时增加
                $saveData = ['bought_class'=> ($restGroup['bought_class']+$input['hours']),'rest_of_class'=>($restGroup['rest_of_class']+$input['hours'])];
                break;
              case 2:
                //课时减少
                $saveData = ['bought_class'=> ($restGroup['bought_class']-$input['hours']),'rest_of_class'=>($restGroup['rest_of_class']-$input['hours'])];
                break;
          }

          return $dataObject->allowField(true)->save($saveData,$where);


       }
     );
   }
}
